package 
{
	import com.adobe.utils.AGALMiniAssembler;
	import com.adobe.utils.PerspectiveMatrix3D;
	import com.magirard.project.camera.BaseCamera;
	import com.magirard.project.entity.StaticMesh;
	import com.magirard.project.manager.io.InputManager;
	import com.magirard.project.manager.renderer.Renderer;
	import com.magirard.project.shader.IBaseShader;
	import com.magirard.project.shader.SimpleTextureShader;
	import com.magirard.project.texture.TextureManager;
	import com.magirard.project.util.ObjParser;
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.Sprite;
	import flash.display.Stage3D;
	import flash.display3D.Context3D;
	import flash.display3D.Context3DProgramType;
	import flash.display3D.Context3DRenderMode;
	import flash.display3D.Context3DTextureFormat;
	import flash.display3D.Context3DVertexBufferFormat;
	import flash.display3D.IndexBuffer3D;
	import flash.display3D.Program3D;
	import flash.display3D.textures.Texture;
	import flash.display3D.VertexBuffer3D;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.geom.Matrix;
	import flash.geom.Matrix3D;
	import flash.geom.Vector3D;
	import flash.ui.Keyboard;
	
	public class Main extends Sprite 
	{
		static public const MOUSE_SENSITIVITY:int = 10;
		[Embed (source = "brick.jpg")]
		private var mTextureBitmap:Class;
		
		[Embed (source = "spaceship.obj", mimeType = "application/octet-stream")]
		private var mMyObjData:Class;
		
		private var mFrameCounter:int;
		private var mTextureManager:TextureManager;
		private var mCamera:BaseCamera;
		
		private var mIsMouseDown:Boolean;
		private var mLastMouseX:int;
		private var mLastMouseY:int;
		
		public function Main():void 
		{
			if (stage) 
			{
				Init();
			}
			else 
			{
				addEventListener(Event.ADDED_TO_STAGE, Init);
			}
		}
		
		private function Init(aEvent:Event = null):void 
		{
			if (hasEventListener(Event.ADDED_TO_STAGE))
			{
				removeEventListener(Event.ADDED_TO_STAGE, Init);
			}
			
			mCamera = new BaseCamera();
			mCamera.MoveBackward(3);
			
			Renderer.addEventListener(Event.CONTEXT3D_CREATE, OnContextReady, false, 0, true);
			Renderer.Init(stage.stageWidth, stage.stageHeight, mCamera);
			
			stage.addEventListener(MouseEvent.MOUSE_DOWN, OnMouseDown, false, 0, true);
			stage.addEventListener(MouseEvent.MOUSE_UP, OnMouseUp, false, 0, true);

		}
		
		private function OnMouseUp(e:MouseEvent):void 
		{
			mIsMouseDown = false;
		}
		
		private function OnMouseDown(e:MouseEvent):void 
		{
			mIsMouseDown = true;
		}
		
		private function OnContextReady(aEvent:Event):void 
		{
			if (Renderer.hasEventListener(Event.CONTEXT3D_CREATE))
			{
				Renderer.removeEventListener(Event.CONTEXT3D_CREATE, OnContextReady);
			}
			
			InputManager.Init(stage);
			var objData:ObjParser = new ObjParser(mMyObjData, Renderer.Context3d, 1, true, true);
			var texture:Texture = TextureManager.CreateTextureWithMipMap(Renderer.Context3d, new mTextureBitmap());
			
			var RANDOM_SIZE:Number = 20;
			
			for (var i:int = 0; i < 30; i++)
			{
				var spaceship:StaticMesh = new StaticMesh(Renderer.Context3d, objData, texture);
				var shader:IBaseShader = new SimpleTextureShader();
				shader.Init(Renderer.Context3d);
				shader.Compile();
				spaceship.Shader = shader;
				spaceship.Position = new Vector3D(RANDOM_SIZE * Math.random() - RANDOM_SIZE / 2, RANDOM_SIZE * Math.random() - RANDOM_SIZE / 2, RANDOM_SIZE * Math.random() - RANDOM_SIZE / 2);
				Renderer.AddEntity(spaceship);
			}

			addEventListener(Event.ENTER_FRAME, Update, false, 0, true);
			
		}

		private function Update(e:Event):void 
		{
			var displayDebug:Boolean = false;
			
			if (InputManager.IsKeyDown(Keyboard.LEFT) || InputManager.IsKeyDown(Keyboard.A))
			{
				mCamera.MoveLeft(0.1);
				displayDebug = true;
			}
			if (InputManager.IsKeyDown(Keyboard.RIGHT) || InputManager.IsKeyDown(Keyboard.D))
			{
				mCamera.MoveRight(0.1);
				displayDebug = true;
			}
			if (InputManager.IsKeyDown(Keyboard.DOWN) || InputManager.IsKeyDown(Keyboard.S))
			{
				mCamera.MoveBackward(0.1);
				displayDebug = true;
			}
			if (InputManager.IsKeyDown(Keyboard.UP) || InputManager.IsKeyDown(Keyboard.W))
			{
				mCamera.MoveForward(0.1);
				displayDebug = true;
			}
			
			//position:Vector3D(-0.041886404156684875, -0.01047175470739603, -3.399689197540283)
			//position:Vector3D(-0.05375327914953232, -0.016405021771788597, -3.899498224258423)
			
			if (mIsMouseDown)
			{
				var diffX:Number = mouseX - mLastMouseX;
				var diffY:Number = mouseY - mLastMouseY;
				
				mCamera.RotateAroundYAxis(diffX / MOUSE_SENSITIVITY);
				mCamera.RotateAroundXAxis(diffY / MOUSE_SENSITIVITY);
				
				displayDebug = true;			
			}
			
			if (displayDebug)
			{
				//trace("position:" + mCamera.ViewMatrix.position.toString());
				//trace("rawData:" + mCamera.ViewMatrix.rawData.toString());
			}
			
			mLastMouseX = mouseX;
			mLastMouseY = mouseY;
			
			mFrameCounter++;
			Renderer.Render();
		}
	}
	
}